#include "Self_Math.h"

double func_pow(double x,int k)
{
    if(k > 0)
    {
        return x * func_pow(x,k-1);
    }
    else if(k == 0)
    {
        return 1;
    }
    else
    {
        return 1.0/func_pow(x,-k);
    }
}

double func_sqrt(double x)
{
    double j,k;
    j = 0.0;
    k = x/2;
    while(j != k)
    {
        j = k;
        k = (j+x/j)/2;
    }
    return j;
}

double func_abs(double x)
{
    if(x < 0)return -x;
    else return x;
}
double func_cos(double x)
{
    x = func_abs(x);
    int t,q=1;
    double term,factorial = 1.0,sum2 = 1,sxm,sum1 = 0;
    for(t = 2;;t++)
    {
        factorial = factorial*t;
        if(t%2 == 0)
        {
            sum1 = sum2;
            q = q*(-1);
            sxm = func_abs(func_pow(x,t));
            term = sxm/factorial;
            sum2 = q*term+sum2;
        }
        if(func_abs(sum2-sum1)<=1e-13)
        {
            break;
        }
    }
    return sum2;
}

double func_sin(double x)
{
    int counter = 0;
    if(x < 0)
    {
        counter = 1;
    }
    else
    {
        counter = 0;
    }
    x = func_abs(x);
    int t,q = 1;
    double term,factorial = 1.0,sum2,sxm,sum1 = 0;
    sum2 = x;
    for(t = 2;;t++)
    {
        factorial = factorial*t;
        if(t%2!=0)
        {
            sum1 = sum2;
            q=q*(-1);
            sxm=func_abs(func_pow(x,t));
            term = sxm/factorial;
            sum2 = q*term+sum2;
        }
        if(func_abs(sum2-sum1)<=1e-13)
        {
            break;
        }
    }
    if(counter == 1)
    {
        sum2 = -sum2;
        return sum2;
    }
    else{return sum2;}
}

double func_atan(double x) {
  if (x == 0.0) {
    return 0.0;
  }

  if (x == 1.0) {
    return 3.141592 / 4;
  }

  if (func_abs(x) < 1.0) {
    double sum = 0.0;
    double term = x;
    double power = x;
    int n = 1;

    while (func_abs(term) > 1e-13) {
      sum += term;
      power *= -x * x;
      term = power / (2 * n + 1);
      n++;
    }

    return sum;
  }

  if (x > 1.0) {
    return 3.141592 / 2 - func_atan(1 / x);
  } else {
    return -3.141592 / 2 + func_atan(-1 / x);
  }
}

double func_atan2(double y,double x)
{
    if(x > 0)
    {
        return func_atan(y/x);
    }
    else if(x < 0)
    {
        if(y >= 0)
        {
            return func_atan(y/x) + 3.141593;
        }
        else
        {
            return func_atan(y/x) - 3.141593;
        }
    }
    else
    {
        if(y > 0)return 1.570796;
        else if(y < 0)return -1.570796;
        else return 0;
    }
}

double func_asin2(double x)
{
    x = x/func_sqrt(1-func_pow(x,2));
    return func_atan(x);
}
